package myjava.arrays;

import java.util.Arrays;

public class Root {

   public static void main(String[] args) {

      // first of all!
      System.out.println((new int[123]) instanceof Object);

      // # ISTANZIAZIONE
      int[] numbers = new int[3];
      String[] names = new String[3];
      boolean[] bool = new boolean[2];
      Object[] objs = new Object[2];
      // ma anche tipi creati ad hoc
      Developer[] devs = new Developer[3];

      // all elements are set to null, 0 or false
      System.out.println(names[1]);
      System.out.println(numbers[2]);
      System.out.println(bool[1]);
      System.out.println(objs[1]);



      // FUZZY NOTATIONS (la seconda e' lecita ma sconsigliata)
      int[] nonFuzzyNum = new int[3];
      int   veryFuzzyNum[] = new int[3];



      // DIMENSIONE DIMENSIONE DIMENSIONE!
      // la dimensione deve sempre essere settata a instantiation time
      int[] setDimension = new int[222];
      // int[] notSetDimension = new int[];



      // # INIZIALIZZAZIONE
      // boring way
      numbers[0] = 1;
      numbers[1] = 2;
      numbers[2] = 3;
      numbers[4] = 3;
      // cool way
      String[] cities = {"Zuric", "Paname", "London", "Beirut", "NYC"};

      /* but this won't work : this notation must be used straight away
       * you can't instantiate and then initialize on a different line */
      // String[] cities2;
      // cities2 = {"Zuric", "Paname", "London", "Beirut", "NYC"};

      // cool anonymous shit!
      String x = new String[] {"fabs", "paolo", "pasqualiera"} [1];

      // # LOOPING ...
      // boring way
      for (int i = 0; i < numbers.length; i++) {
         System.out.println(numbers[i]);
      }

      // cool way
      for (String c : cities) {
         System.out.println(c);
      }

      /*
      When you declare an array variable, Java reserves only enough
      memory for a reference (Java's name for "pointer") to an array object.
      When an array object is created with "new", a reference is returned, and
      that reference can then be assigned to a variable. When you assign
      one array variable to another, only the reference is copied. For example:
       */

      int[] numbersRef;
      numbersRef = numbers;
      numbersRef[2] = 42;
      // sovrascrive l'elemento in posizione 3 dell'array puntato da entrambi i reference
      System.out.println("in numbers: " + numbers[2]); // 42
      System.out.println("in numbersRef: " + numbersRef[2]); // 42

      // la classe java.util.Arrays offre una botto di metodi statici
      // per operare sugli array

      // # binarySearch
      String myCity = "NYC";
      int position = Arrays.binarySearch(cities, myCity);
      System.out.println("indice di NYC in the array: " + position);

      // # sort
      Arrays.sort(cities);
      System.out.println(Arrays.toString(cities));

      // # copyOf
      // permette di copiare un array : ricorda che gli array sono
      // oggetti e l'assegnazione porta alla creazione di un reference
      // e non di una copia reale!

      String[] copyOfCities = Arrays.copyOf(cities, cities.length);
      System.out.println(Arrays.toString(copyOfCities));
      // per provare che e' una copia per valore faccio: 
      copyOfCities[0] = "Rome";
      System.out.println("copia per valore di 'cities' e override del valore Beirut : " + Arrays.toString(copyOfCities));
      System.out.println("vecchio array 'cities' : " + Arrays.toString(cities));

   }
}

class Developer {
   ;
}
